package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.feign.BehaviorFeign;
import com.heima.article.feign.UserFeign;
import com.heima.article.mapper.*;
import com.heima.article.service.ApArticleService;
import com.heima.common.constants.article.ArticleConstans;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.dtos.ArticleInfoDto;
import com.heima.model.article.mess.ArticleVisitStreamMess;
import com.heima.model.article.pojos.*;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.behavior.pojos.ApBehaviorEntry;
import com.heima.model.behavior.pojos.ApLikesBehavior;
import com.heima.model.behavior.pojos.ApUnlikesBehavior;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.model.user.pojos.ApUserFollow;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import io.seata.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {
    @Autowired
    private BehaviorFeign behaviorFeign;
    @Autowired
    private UserFeign userFeign;
    @Autowired
    private ApCollectionBehaviorMapper apCollectionMapper;
    @Autowired
    private AuthorMapper authorMapper;

    @Autowired
    private ApArticleMapper apArticleMapper;
    @Autowired
    private ApArticleConfigMapper apArticleConfigMapper;
    @Autowired
    private ApArticleContentMapper apArticleContentMapper;

    @Value("${fdfs.url}")
    private String url;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;



    @Override
    public ResponseResult load2(ArticleHomeDto dto, Short loadType, boolean firstPage) {
        if(firstPage){
            String jsonStr = redisTemplate.opsForValue().get(ArticleConstans.HOT_ARTICLE_FIRST_PAGE + dto.getTag());
            if(StringUtils.isNotBlank(jsonStr)){
                List<HotArticleVo> hotArticleVoList = JSON.parseArray(jsonStr, HotArticleVo.class);
                if(!hotArticleVoList.isEmpty()&& hotArticleVoList.size() > 0){
                    ResponseResult responseResult = ResponseResult.okResult(hotArticleVoList);
                    responseResult.setHost(url);
                    return responseResult;
                }
            }
        }
        return load(loadType,dto);
    }










    @Override
    public ResponseResult loadArticleBehavior(ArticleInfoDto dto) {
        boolean isfollow = false,islike=false,isunlike=false,iscollection=false;
        if (dto==null||dto.getArticleId()==null||dto.getAuthorId()==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        ApUser user = AppThreadLocalUtils.getUser();
        Integer id = user==null? null:user.getId();
        ApBehaviorEntry apBehaviorEntry = behaviorFeign.findByUserIdOrEntryId(id, dto.getEquipmentId());
        if (apBehaviorEntry==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"没有与此对应的实体对象");
        //// 根据ID 或 文章ID查询不喜欢行为
        ApUnlikesBehavior apUnlikesBehavior = behaviorFeign.findUnLikeByArticleIdAndEntryId(apBehaviorEntry.getId(), dto.getArticleId());
        if(apUnlikesBehavior!=null && apUnlikesBehavior.getType() == 0 ){
            isunlike = true;
        }

         //根据ID 或 文章ID查询点赞行为
        ApLikesBehavior likesBehavior = behaviorFeign.findLikeByArticleIdAndEntryId(apBehaviorEntry.getId(), dto.getArticleId(), ApLikesBehavior.Type.ARTICLE.getCode());
        if(likesBehavior!=null && likesBehavior.getOperation()==0){
            islike = true;
        }
        // 根据ID 或 文章ID查询收藏行为
        ApCollection apCollection = apCollectionMapper.selectOne(
                Wrappers.<ApCollection>lambdaQuery()
                        .eq(ApCollection::getEntryId, apBehaviorEntry.getId())
                        .eq(ApCollection::getArticleId, dto.getArticleId())
                        .eq(ApCollection::getType, 0)
        );
        if(apCollection!=null){
            iscollection = true;
        }
        ApAuthor apAuthor = authorMapper.selectById(dto.getAuthorId());
        if(apAuthor!=null){
            ApUserFollow apUserFollow = userFeign.findByUserIdAndFollowId(id, apAuthor.getUserId());
            if (apUserFollow !=null) {
                isfollow = true;
            }
        }
            Map resultMap = new HashMap();
            resultMap.put("isfollow",isfollow);
            resultMap.put("islike",islike);
            resultMap.put("isunlike",isunlike);
            resultMap.put("iscollection",iscollection);
            return ResponseResult.okResult(resultMap);

    }

    //app端查询文章详细信息
    @Override
    public ResponseResult loadArticleInfo(ArticleInfoDto dto) {
        Map<String,Object> map = new HashMap<>();
        if (dto==null||dto.getArticleId()==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        ApArticleConfig apArticleConfig = apArticleConfigMapper.selectOne(Wrappers.<ApArticleConfig>lambdaQuery().eq(ApArticleConfig::getArticleId, dto.getArticleId()));
        if (apArticleConfig==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        if (!apArticleConfig.getIsDelete() && !apArticleConfig.getIsDown()) {
            ApArticleContent apArticleContent = apArticleContentMapper.selectOne(Wrappers.<ApArticleContent>lambdaQuery().eq(ApArticleContent::getArticleId, dto.getArticleId()));

            String content = apArticleContent.getContent();

            List<Map> maps = JSONArray.parseArray(content, Map.class);
            List<Map> collect = maps.stream().map(
                    m -> {
                        if ("image".equals(m.get("type"))) {
                            String imageUrl = (String) m.get("value");
                            m.put("value", url + imageUrl);
                        }
                        return m;
                    }
            ).collect(Collectors.toList());
            apArticleContent.setContent(JSON.toJSONString(collect));

            map.put("content",apArticleContent);
        }
        map.put("config",apArticleConfig);
        ResponseResult responseResult = ResponseResult.okResult(map);
        responseResult.setHost(url);
        return responseResult;
    }




    @Override
    public void updateApArticle(ArticleVisitStreamMess mess) {
        ApArticle apArticle = getById(mess.getArticleId());
        if (apArticle==null)
            log.error("该文章不存在 文章id为{}",mess.getArticleId());
        apArticle.setLikes((int)(apArticle.getLikes()==null?mess.getLike():apArticle.getLikes()+mess.getLike()));
        apArticle.setComment((int)(apArticle.getComment()==null?mess.getComment():apArticle.getComment()+mess.getComment()));
        apArticle.setViews((int)(apArticle.getViews()==null?mess.getView():apArticle.getViews()+mess.getView()));
        apArticle.setCollection((int)(apArticle.getCollection()==null?mess.getCollect():apArticle.getCollection()+mess.getCollect()));
        updateById(apArticle);

        Integer score = computeScore(apArticle) * 3;

        updateHotArticleCache(apArticle,score,ArticleConstans.HOT_ARTICLE_FIRST_PAGE+apArticle.getChannelId());
        updateHotArticleCache(apArticle,score,ArticleConstans.HOT_ARTICLE_FIRST_PAGE+ArticleConstans.DEFAULT_TAG);
    }

    private void updateHotArticleCache(ApArticle apArticle, Integer score, String cacheStr) {
        boolean flag = false;
        String str = stringRedisTemplate.opsForValue().get(cacheStr);
        if (StringUtils.isNotBlank(str)) {
            List<HotArticleVo> list = JSON.parseArray(str, HotArticleVo.class);
            for (HotArticleVo hotArticleVo : list) {
                if (hotArticleVo.getId().equals(apArticle.getId())){
                hotArticleVo.setScore(score);
                flag=true;
                break;
                }
            }
            if (!flag){
                HotArticleVo hotArticleVo = new HotArticleVo();
                BeanUtils.copyProperties(apArticle,hotArticleVo);
                hotArticleVo.setScore(score);
                list.add(hotArticleVo);
            }
            list= list.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).limit(30).collect(Collectors.toList());
            stringRedisTemplate.opsForValue().set(cacheStr,JSON.toJSONString(list));
        }
    }

    private Integer computeScore(ApArticle apArticle) {
        Integer score = 0;
        if (apArticle.getLikes() != null) {
            score += apArticle.getLikes() * ArticleConstans.HOT_ARTICLE_LIKE_WEIGHT;
        }
        if (apArticle.getViews() != null) {
            score += apArticle.getViews();
        }
        if (apArticle.getComment() != null) {
            score += apArticle.getComment() * ArticleConstans.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        if (apArticle.getCollection() != null) {
            score += apArticle.getCollection() * ArticleConstans.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        return score;
    }






    //search微服务远程调用
    @Override
    public Map findArticle(Long id) {
        Map<String,Object> map = new HashMap();
        ApArticle apArticle = getById(id);
        ApArticleContent articleContent = apArticleContentMapper.selectOne(
                Wrappers.<ApArticleContent>lambdaQuery()
                        .eq(ApArticleContent::getArticleId, id)
        );
        map.put("id", String.valueOf(apArticle.getId()));
        map.put("publishTime", apArticle.getPublishTime());
        map.put("layout", apArticle.getLayout());
        map.put("images", apArticle.getImages());
        map.put("authorId", apArticle.getAuthorId());
        map.put("title", apArticle.getTitle());
        if(articleContent!=null){
            map.put("content",articleContent.getContent());
        }
        return map;
    }

    @Override
    public ResponseResult load(Short loadtype, ArticleHomeDto dto) {
        if (dto==null)
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        if (dto.getSize()==null)
            dto.setSize(10);
        if (dto.getMaxBehotTime()==null)
            dto.setMaxBehotTime(new Date());
        if (dto.getMinBehotTime()==null)
            dto.setMinBehotTime(new Date());
        if (!ArticleConstans.LOADTYPE_LOAD_MORE.equals(loadtype)&&!ArticleConstans.LOADTYPE_LOAD_NEW.equals(loadtype))
            loadtype=ArticleConstans.LOADTYPE_LOAD_MORE;
        if (StringUtils.isBlank(dto.getTag()))
            dto.setTag(ArticleConstans.DEFAULT_TAG);
        List<ApArticle> apArticles = apArticleMapper.loadArticleList(dto, loadtype);
        ResponseResult responseResult = ResponseResult.okResult(apArticles);
        responseResult.setHost(url);
        return responseResult;
    }



}